from logging import Logger
from pathlib import Path
from typing import Any
import time
import traceback
from kubernetes import config, client
import yaml
from performance.runner.logger import create_step_logger
from performance.runner.constants import (
    KUBECONFIG_PATH,
    RESOURCE_MONITOR_INTERVAL, 
    RESOURCE_MONITOR_FAILED_THRESHOLD, 
    RESOURCE_MONITOR_ROUND, 
    POD_CATEGORY_PATH
)
from performance.runner.resource_monitor.resource_monitor import ResourceMonitor
from .kubeconfig_fetcher import fetch_and_save_kubeconfig, validate_kubeconfig


def _load_pod_category(feature_category: str, step_logger: Logger):
    """
    加载 pod_categorization.yaml，获取指定 feature_category 下的 pod 列表，
    返回 { 'namespace_name': {'cpu': None, 'mem': None} } 结构
    """
    if not KUBECONFIG_PATH.exists():
        step_logger.warning("本地 kubeconfig 文件不存在，尝试自动拉取远程 kubeconfig 文件...")
        fetch_and_save_kubeconfig()
    config.load_kube_config(config_file=str(KUBECONFIG_PATH))
    core_v1 = client.CoreV1Api()
    with open(str(POD_CATEGORY_PATH), 'r', encoding='utf-8') as f:
        data = yaml.safe_load(f)

    if not data:
        return {}

    pod_category = next((c for c in data if c['category'] == feature_category))
    if not pod_category:
        return {}
    
    pod_dict = {}
    for rule in pod_category['rules']:
        namespace = rule['namespace']
        for selector in rule['labelSelectors']:
            pod_list = core_v1.list_namespaced_pod(namespace, label_selector=selector)
            for pod in pod_list.items:
                name = pod.metadata.name
                # 将 namespace 和 name 用下划线连接, 因为k8s的pod名称不能包含下划线，便于后续拆解ns与name
                pod_dict[f"{namespace}_{name}"] = {'cpu': None, 'mem': None}

    return pod_dict


def exec_resource_monitor(feature_category: str, resource_log_path: Path, csv: bool = False):
    """
    执行资源监控主流程。
    :param feature_category: 特性类别字符串。
    :return: 成功返回 True，失败返回 False。
    """
    step_logger = create_step_logger(resource_log_path, feature_category)

    step_logger.info(f"加载 [{feature_category}] 的监控 Pod 列表。")
    pod_resource_dict: dict[Any, Any] = _load_pod_category(feature_category, step_logger)
    if not pod_resource_dict:
        step_logger.info(f"未找到 [{feature_category}] 的监控 Pod 列表，退出监控。")
        return

    try:
        step_logger.info(f"为 [{feature_category}] 开启资源监控器。")
        monitor = ResourceMonitor(feature_category, pod_resource_dict, step_logger, resource_log_path)
        monitor.enable_detail_logging = True
    except Exception as e:
        step_logger.error(f"资源监控开启失败: {e} \n {traceback.format_exc()}")
        return

        
    succeed_round = 0
    fail_round = 0
    while succeed_round < RESOURCE_MONITOR_ROUND:
        try:
            monitor.monitor_pod_resources()
            succeed_round = succeed_round + 1
            step_logger.info(f"[{feature_category}] 第 {succeed_round} 轮资源监控数据采集成功完成。")
        except Exception as e:
            step_logger.error(f"资源监控失败: {e} \n {traceback.format_exc()}")
            fail_round = fail_round + 1
            if fail_round > RESOURCE_MONITOR_FAILED_THRESHOLD:
                return
        time.sleep(RESOURCE_MONITOR_INTERVAL)

    step_logger.info(f"完成全部 {RESOURCE_MONITOR_ROUND} 轮采样，退出任务")

    if not csv:
        return

    step_logger.info(f'输出结果到csv...')
    parsed_data = monitor.log_parser.process_all_logs()
    if parsed_data:
        monitor.log_parser.save_to_csv(parsed_data, resource_log_path / 'result.csv')